﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;
using Universum.Model.Services;
using Universum.Model.Domain;
using System.Linq.Expressions;
using Microsoft.Web.Mvc;
using Microsoft.Web.Mvc.Internal;
using System.Security.Principal;
using StructureMap;
using Universum.Infrastructure.Configuration;
namespace Universum.Infrastructure.Utils.Extensions
{
	
	/// <summary>
	/// Adds miscelanious extensions to the <c ref="System.Web.Mvc.HtmlHelper">HtmlHelper</c> class.
	/// </summary>
	public static class HtmlHelperExtension
	{
		/// <summary>
		/// Generates an RssLink
		/// </summary>
		/// <param name="html">The <c ref="System.Web.Mvc.HtmlHelper">HtmlHelper</c>  instance</param>
		/// <returns>A string for the RssLink</returns>
		public static string RssLink(this HtmlHelper html)
		{
			return string.Format(@"<link id=""RssLink"" title=""RSS"" type=""application/rss+xml"" rel=""alternate"" href=""{0}""/>",
				ExtractUrl<Universum.Controllers.RssController>(html,it=>it.Content())
				);
		}
		/// <summary>
		/// Computest the Time passed since the given date time
		/// </summary>
		/// <param name="html">The <c ref="System.Web.Mvc.HtmlHelper">HtmlHelper</c>  instance</param></param>
		/// <param name="dateTime">The given date</param>
		/// <returns>A string format</returns>
		public static string TimePassedSince(this HtmlHelper html, DateTime dateTime)
		{
			return ObjectFactory.GetInstance<IDurationService>().Since(dateTime);
		}
		/// <summary>
		/// Get the representational image for the given image
		/// </summary>
		/// <param name="html">The <c ref="System.Web.Mvc.HtmlHelper">HtmlHelper</c>  instance</param>
		/// <param name="resource">The resource instance</param>
		/// <returns></returns>
		public static string ResourceRepresentation(this HtmlHelper html,
			Resource resource)
		{
			TagBuilder tag = new TagBuilder("img");
			tag.MergeAttribute("src", ""
				
				);
			return tag.ToString();
		}
		/// <summary>
		/// Begins the link statement
		/// </summary>
		/// <typeparam name="TController">The controller type</typeparam>
		/// <param name="helper">The <c ref="System.Web.Mvc.HtmlHelper">HtmlHelper</c>  instance</param>
		/// <param name="action">An action</param>
		public static void BeginLink<TController>(this HtmlHelper helper,
   Expression<Action<TController>> action
   ) where TController : Controller
		{
			BeginLink(helper,
			 action,
			 new { });
		}
		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="TController">The controller type</typeparam>
		/// <param name="helper">The <c ref="System.Web.Mvc.HtmlHelper">HtmlHelper</c>  instance</param>
		/// <param name="action"></param>
		/// <param name="htmlAttributes"></param>
		public static void BeginLink<TController>(this HtmlHelper helper,
		 Expression<Action<TController>> action,
		 object htmlAttributes) where TController : Controller
		{
			BeginLink(helper,
			 action,
			  new RouteValueDictionary(htmlAttributes));
		}

		/// <summary>
		/// This method returns the href="{region}" region using
		/// the supplied action
		/// </summary>
		/// <typeparam name="TController"></typeparam>
		/// <param name="helper"></param>
		/// <param name="action"></param>
		/// <returns></returns>
		public static string RouteUrl<TController>(this HtmlHelper helper,
			 Expression<Action<TController>> action
		) where TController : Controller
		{
			string href = Microsoft.Web.Mvc.LinkExtensions.BuildUrlFromExpression(helper, action);
			return href;
		}
		/// <summary>
		/// Begins a {{{a href}}} element
		/// </summary>
		/// <typeparam name="TController">Controller</typeparam>
		/// <param name="helper">The HtmlHelper </param>
		/// <param name="action">The controller action to be invoked</param>
		/// <param name="htmlAttributes">The additional html attributes to be used</param>
		public static void BeginLink<TController>(this HtmlHelper helper,
		 Expression<Action<TController>> action,
		 IDictionary<string, object> htmlAttributes) where TController : Controller
		{
			TagBuilder builder = new TagBuilder("a");
			builder.MergeAttributes(htmlAttributes);

			string href = ExtractUrlWithUsernameInRequest<TController>(helper, action);
			//Microsoft.Web.Mvc.LinkExtensions.BuildUrlFromExpression(helper, action);
			builder.MergeAttribute("href", href);

			HttpResponseBase httpResponse = helper.ViewContext.HttpContext.Response;
			httpResponse.Write(builder.ToString(TagRenderMode.StartTag));

		}
		/// <summary>
		/// Extracts the URL and also includes the Username that is 
		/// the Current Principal
		/// </summary>
		/// <typeparam name="TController">Controller</typeparam>
		/// <param name="helper">The helper</param>
		/// <param name="action">The action</param>
		/// <returns></returns>
		private static string ExtractUrlWithUsernameInRequest<TController>(HtmlHelper helper, Expression<Action<TController>> action)
			where TController:Controller
		{
			RouteValueDictionary routeValuesFromExpression =
						 ExpressionHelper.GetRouteValuesFromExpression<TController>(action);
			if (null != HttpContext.Current.User.Identity.Name)
			{
				routeValuesFromExpression.Add("username", helper.UsernameInRequest() ?? HttpContext.Current.User.Identity.Name);
			}

			VirtualPathData virtualPath = helper
				.RouteCollection.GetVirtualPath(
				helper.ViewContext.RequestContext,
				routeValuesFromExpression);


			string href = virtualPath.VirtualPath;
			return href;
		}
		/// <summary>
		/// Begins a {{{a href}}} tag using the current principal
		/// </summary>
		/// <typeparam name="TController"></typeparam>
		/// <param name="helper"></param>
		/// <param name="action"></param>
		public static void BeginUserLink<TController>(this HtmlHelper helper,
   Expression<Action<TController>> action
   ) where TController : Controller
		{
			BeginUserLink(helper,
			 action,
			 new { });
		}
		/// <summary>
		/// Begins a {{{a href}}} tag using the current principal
		/// </summary>
		/// <typeparam name="TController"></typeparam>
		/// <param name="helper"></param>
		/// <param name="action"></param>
		public static void BeginUserLink<TController>(this HtmlHelper helper,
		 Expression<Action<TController>> action,
		 object htmlAttributes) where TController : Controller
		{
			BeginUserLink(helper,
			 action,
			  new RouteValueDictionary(htmlAttributes));
		}
		/// <summary>
		/// Begins a {{{a href}}} tag using the current principal
		/// </summary>
		/// <typeparam name="TController"></typeparam>
		/// <param name="helper"></param>
		/// <param name="action"></param>
		public static void BeginUserLink<TController>(this HtmlHelper helper,
		 Expression<Action<TController>> action,
		 IDictionary<string, object> htmlAttributes) where TController : Controller
		{
			TagBuilder builder = new TagBuilder("a");
			builder.MergeAttributes(htmlAttributes);

			string href = ExtractUrlWithUsername<TController>(helper, action);
			//Microsoft.Web.Mvc.LinkExtensions.BuildUrlFromExpression(helper, action);
			builder.MergeAttribute("href", href);

			HttpResponseBase httpResponse = helper.ViewContext.HttpContext.Response;
			httpResponse.Write(builder.ToString(TagRenderMode.StartTag));

		}
		/// <summary>
		/// Begins a {{{a href}}} tag using the given username
		/// </summary>
		/// <typeparam name="TController">Controller</typeparam>
		/// <param name="helper">The helper</param>
		/// <param name="action">The action</param>
		/// <param name="username">The username</param>
		public static void BeginLinkWithUsername<TController>(this HtmlHelper helper, Expression<Action<TController>> action, string username) where TController : Controller
		{
			RouteValueDictionary routeValuesFromExpression =
						 ExpressionHelper.GetRouteValuesFromExpression<TController>(action);
			if (null != HttpContext.Current.User.Identity.Name)
			{
				routeValuesFromExpression.Add("username", username);
			}

			VirtualPathData virtualPath = helper
				.RouteCollection.GetVirtualPath(
				helper.ViewContext.RequestContext,
				routeValuesFromExpression);


			string href = virtualPath.VirtualPath;
			HttpResponseBase httpResponse = helper.ViewContext.HttpContext.Response;
			httpResponse.Write(string.Format("<a href={0}>", href));
			 

		}

		/// <summary>
		/// Extracts a url
		/// </summary>
		/// <typeparam name="TController">Controller</typeparam>
		/// <param name="helper">The helper</param>
		/// <param name="action">The action</param>
		/// <returns>The url</returns>
		public static string ExtractUrl<TController>(this HtmlHelper helper, Expression<Action<TController>> action) where TController : Controller
		{
			RouteValueDictionary routeValuesFromExpression =
						 ExpressionHelper.GetRouteValuesFromExpression<TController>(action);
			
			VirtualPathData virtualPath = helper
				.RouteCollection.GetVirtualPath(
				helper.ViewContext.RequestContext,
				routeValuesFromExpression);


			string href = virtualPath.VirtualPath;
			return href;
		}
		/// <summary>
		/// Extracts the username
		/// </summary>
		/// <typeparam name="TController"></typeparam>
		/// <param name="helper"></param>
		/// <param name="action"></param>
		/// <returns></returns>
		public static string ExtractUrlWithUsername<TController>(this HtmlHelper helper, Expression<Action<TController>> action) where TController : Controller
		{
			RouteValueDictionary routeValuesFromExpression =
						 ExpressionHelper.GetRouteValuesFromExpression<TController>(action);
			if (null != HttpContext.Current.User.Identity.Name)
			{
				routeValuesFromExpression.Add("username",HttpContext.Current.User.Identity.Name);
			}

			VirtualPathData virtualPath = helper
				.RouteCollection.GetVirtualPath(
				helper.ViewContext.RequestContext,
				routeValuesFromExpression);


			string href = virtualPath.VirtualPath;
			return href;
		}
		/// <summary>
		///  Ends the link element
		/// </summary>
		/// <param name="helper"></param>
		public static void EndLink(this HtmlHelper helper)
		{
			TagBuilder tagBuilder = new TagBuilder("a");
			HttpResponseBase httpResponse = helper.ViewContext.HttpContext.Response;
			httpResponse.Write(tagBuilder.ToString(TagRenderMode.EndTag));
		}
		/// <summary>
		/// Textual user link
		/// </summary>
		/// <param name="html">helper</param>
		/// <param name="linkText">text</param>
		/// <param name="actionname">action name</param>
		/// <param name="routes">routes</param>
		/// <returns></returns>
		public static string UserActionLink(this HtmlHelper html,
			string linkText,
			string actionname,
			object routes)
		{
			var routeValuesDictionary
				= new RouteValueDictionary(routes);
			if (null != HttpContext.Current.User.Identity.Name)
			{
				routeValuesDictionary.Add(
					"username", HttpContext.Current.User.Identity.Name);
			}
			return
				html.ActionLink(linkText, actionname,
				routeValuesDictionary);

		}
		public static string UserActionLink<TController>
			(this HtmlHelper html,
			Expression<Action<TController>> action,
			string linkText) where TController : Controller
		{
			return html.UserActionLink<TController>(
				action, linkText, null, null);

		}
		public static string UserActionLink<TController>
			(this HtmlHelper html,
			Expression<Action<TController>> action,
			string linkText,
			object routeValues) where TController : Controller
		{
			return html.UserActionLink<TController>(
				action, linkText, routeValues, null);

		}
		public static string UserActionLink<TController>
			(this HtmlHelper html,
			Expression<Action<TController>> action,
			string linkText,
			object routeValues,
			object htmlAttributes) where TController : Controller
		{
			RouteValueDictionary routeValuesFromExpression = ExpressionHelper.GetRouteValuesFromExpression<TController>(action);
			if (null != HttpContext.Current.User.Identity.Name)
			{
				routeValuesFromExpression.Add("username", html.UsernameInRequest() ?? HttpContext.Current.User.Identity.Name);
			}
			if (null != routeValues)
			{
				var appendToRoute = new RouteValueDictionary(routeValues);
				foreach (var key_value in appendToRoute)
				{
					routeValuesFromExpression[key_value.Key] =
					 key_value.Value;
				}

			}
			return html.RouteLink(linkText, routeValuesFromExpression, new RouteValueDictionary(htmlAttributes));


		}
		public static string UserActionLink(
			this HtmlHelper html,
			string linkText,
			string actionName,
			string controllerName
			)
		{
			var routeValues =
							new RouteValueDictionary(
								);
			if (null != HttpContext.Current.User.Identity.Name)
			{
				routeValues.Add("username", HttpContext.Current.User.Identity.Name);
				return html.ActionLink(linkText, actionName, controllerName, routeValues, null);
			}
			return html.ActionLink(linkText,
				actionName,
				controllerName);

		}

		public static string Pager<TController>(this HtmlHelper htmlHelper,
			Expression<Action<TController>> action,
			int pageSize,
			int currentPage,
			int totalItemCount)
			where TController : Controller
		{
			var pager = new Pager<TController>(htmlHelper, action,
				pageSize, currentPage, totalItemCount);
			return pager.ToHtmlString();
		}


		
	}
}
